# from mechine import Heat_recovery_system, steam_turbine, Condenser, D_pre, zero_pre
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import threading
import logging
from bi_mp_pro2 import parallel_optimize
from logging.handlers import RotatingFileHandler
from influxDBturbinecooltest import Real_time_from_other_buffer_to_alg, written_model_data_buffer, History_from_other_buffer_to_alg

###########################最优背压寻找数据##
fan_photo = np.zeros((100, 1), dtype=np.float32)
net_photo = np.zeros((100, 1), dtype=np.float32)

def share_data():
    return fan_photo, net_photo

def setup_logger(thread_name):
    logger = logging.getLogger(thread_name)
    logger.setLevel(logging.DEBUG)  # 设置日志级别

    fmt = "[%(asctime)s-%(threadName)s] (%(filename)s %(lineno)d): %(levelname)s %(message)s"

    # 创建文件处理器
    log_filename = rf".\logs\{thread_name}.log"
    file_handler = RotatingFileHandler(log_filename, mode='a', maxBytes=5 * 1024 * 1024, backupCount=1, encoding="utf-8")
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(logging.Formatter(fmt=fmt, datefmt="%Y-%m-%d %H:%M:%S"))
    logger.addHandler(file_handler)

    return logger

plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体：解决plot不能显示中文问题
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像时负号'-'显示为方块的问题

def opt_core(logger):
    global fan_photo
    global net_photo
    while True:
        # 从buffer中读取全部测点最新数据
        need_time, latest_data_other_new = Real_time_from_other_buffer_to_alg(logger)
        current_data_time_new = np.array([need_time])
        # TODO: 筛选需要的测点形成字典输入算法
        logger.info(f"背压寻优算法输入实时数据：{latest_data_other_new}")
        #matrix_best = bp_opt_bisection(latest_data_other_new, logger)
        # current_data_time_new对应的测点名称，需要的有，需要打开数据文件看看需要哪些
        # input_points = ['时间','机组负荷', '主汽压力', '主汽流量', '再热蒸汽压力', '再热蒸汽温度', '凝结水泵出口母管温度',
        #                 '凝结水流量', '主给水流量', '主汽温度', '环境温度', '风机转速', '背压kPa', '背压']
        input_points = [0, 1, 4, 2, 6, 7, 13, 12, 11, 3, 19, 14, 18]
        data_opt = latest_data_other_new[0,:][input_points]
        if data_opt[1]==0:
            matrix_best = np.zeros((1, 3)).astype(np.float32)
        else:
            logger.info(f'输入二分寻优算法数据：{data_opt}')
            # 最优风机转速，背压，功率
            matrix_best, trace_list = parallel_optimize(data=data_opt, simtime=25, sample_time=5, h=0.2, tolerance=0.0005, precision=6, logger=logger)
            matrix_best = matrix_best.reshape(1, 3)
            result_array = np.array(trace_list)
            result_array = result_array[result_array[:, 3].argsort()]
            fan_photo = result_array[:, 3:4]
            net_photo = result_array[:, 1:2]
        # print(f'matrix_best{matrix_best}')
        # matrix_best = np.zeros((1, 3)).astype(np.float32)
        matrix_predict = np.zeros((1, 2)).astype(np.float32)
        matrix_result_assess = np.zeros((1, 4)).astype(np.float32)
        data_model_matrix = np.hstack((current_data_time_new, matrix_predict, matrix_best, matrix_result_assess))
        data_model = data_model_matrix.reshape(-1)
        written_model_data_buffer(data_model)
        logger.info(f"保存模型输出到缓冲池：{data_model_matrix}")
        # matrix_predict = predicts_varsss(config, train_model, logger, device, current_data_df)  # 预测
        # all_new_data = repeat_prediction(current_data_df)  # 修改风机转速为等差数列
        # matrix_best = predicts_varss(config, train_model, logger, device, all_new_data)  # 寻优
        # matrix_result_assess = np.random.rand(1, 4).astype(np.float32)  # 模型评价指标
        # 核心对测点进行筛选，交给算法计算，并返回结果
        # 保存算法输出到model_buffer
        # TODO: 不同算法计算时间可能不同，要分线程计算，异步存储，还是等待所有算法结束

def opt_core2(logger):
    global fan_photo
    global net_photo
    while True:
        # 从buffer中读取全部测点最新数据
        need_time, latest_one_new, latest_n_new, enough_his = History_from_other_buffer_to_alg(logger, n=50)
        current_data_time_new = np.array([need_time])
        # TODO: 筛选需要的测点形成字典输入算法
        logger.info(f"背压寻优算法输入实时数据：{latest_one_new}")
        logger.info(f"背压寻优算法输入历史数据：{latest_n_new}")
        #matrix_best = bp_opt_bisection(latest_data_other_new, logger)
        # current_data_time_new对应的测点名称，需要的有，需要打开数据文件看看需要哪些
        # input_points = ['时间','机组负荷', '主汽压力', '主汽流量', '再热蒸汽压力', '再热蒸汽温度', '凝结水泵出口母管温度',
        #                 '凝结水流量', '主给水流量', '主汽温度', '环境温度', '风机转速', '背压kPa', '背压']
        input_points = [0, 1, 4, 2, 6, 7, 13, 12, 11, 3, 19, 14, 18]
        data_opt = latest_one_new[0,:][input_points]
        if data_opt[1]==0 or not enough_his:
            matrix_best = np.zeros((1, 3)).astype(np.float32)
        else:
            # logger.info(f'输入二分寻优算法数据：{data_opt}')
            # 最优风机转速，背压，功率
            matrix_best, trace_list = parallel_optimize(data=latest_n_new, simtime=25, sample_time=5, h=0.1, tolerance=0.0005, precision=6, logger=logger)
            # TODO: opt2: 先获取历史数据，输入parallel opt函数，注意去除重复数据。
            matrix_best = matrix_best.reshape(1, 3)
            result_array = np.array(trace_list)
            result_array = result_array[result_array[:, 3].argsort()]
            fan_photo = result_array[:, 3:4]
            net_photo = result_array[:, 1:2]
        # print(f'matrix_best{matrix_best}')
        # matrix_best = np.zeros((1, 3)).astype(np.float32)
        matrix_predict = np.zeros((1, 2)).astype(np.float32)
        matrix_result_assess = np.zeros((1, 4)).astype(np.float32)
        data_model_matrix = np.hstack((current_data_time_new, matrix_predict, matrix_best, matrix_result_assess))
        data_model = data_model_matrix.reshape(-1)
        written_model_data_buffer(data_model)
        logger.info(f"保存模型输出到缓冲池：{data_model_matrix}")
        # matrix_predict = predicts_varsss(config, train_model, logger, device, current_data_df)  # 预测
        # all_new_data = repeat_prediction(current_data_df)  # 修改风机转速为等差数列
        # matrix_best = predicts_varss(config, train_model, logger, device, all_new_data)  # 寻优
        # matrix_result_assess = np.random.rand(1, 4).astype(np.float32)  # 模型评价指标
        # 核心对测点进行筛选，交给算法计算，并返回结果
        # 保存算法输出到model_buffer
        # TODO: 不同算法计算时间可能不同，要分线程计算，异步存储，还是等待所有算法结束

def build_opt_alg():
    logger = setup_logger("opt_algs")
    predict_thread = threading.Thread(target=opt_core2, args=(logger,))
    predict_thread.start()